#pragma once

#include "Connection.hpp"
#include "Socket.hpp"
#include "Ioservice.hpp"
#include "Parse.hpp"

#include <memory>

using namespace SocketModule;
class Listener : public Connection
{
public:
    Listener(uint16_t port)
        : _listen_sockfd_ptr(std::make_unique<TcpSocket>()), _port(port)
    {
        _listen_sockfd_ptr->BuildTcpSocketMethod(port);
        SetSockfd(_listen_sockfd_ptr->Fd()); // 设置fd进入Connection
        SetEvents(EPOLLIN | EPOLLET);


        parse.RegisterCal([&](const request &req)
                          { return cal.Execute(req); });
    }
    // 在成功能够插入listener模块之后，编写Recver和io模块  ->io模块(处理inbuffer非阻塞循环读(协议+处理) ，outbuffer(写关心按需设置))
    virtual void Recver() override
    {
        /*listen套接字循环读取缓冲区,直到缓冲区没有数据*/
        while (true) /*这里sockfd内部封装的accept方法我们要把错误宏带出来进行分析，因为宏中存放的是最清晰的错误信息*/
        {
            InetAddr peer;
            int aerrno = 0;
            // accept 非阻塞的时候，就是IO，我们就向处理read一样，处理accept
            int sockfd = _listen_sockfd_ptr->Accepter(&peer, &aerrno);
            if (sockfd > 0)
            {
                // 说明正确accept了
                auto coon = std::make_shared<ioservice>(sockfd);
                LOG(LogLevel::INFO) << "用户信息: " << peer.Addr();
                // 设置进Reactor中,并且将协议的处理方法注册给IOservice模块

                coon->RegisterFunc([&](std::string packge)
                                   { return parse.HandlerBuffer(packge); }); // 将处理的接口注册给ioservice

                GetOwner()->InsertConnection(coon);
            }
            else
            {
                // sockfd<0,根据错误信息判断
                if (aerrno == EAGAIN | aerrno == EWOULDBLOCK)
                {
                    LOG(LogLevel::INFO) << "底层数据读取完毕";
                    break;
                }
                if (aerrno == EINTR)
                {
                    LOG(LogLevel::INFO) << "信号中断";
                    return;
                }
                else
                {
                    LOG(LogLevel::WARNING) << "accetper error ... Ignore"; // 其他的忽略，反正也没有建立连接
                    break;
                }
            }
        }
    }

    virtual void Sender() override
    {
    }

    virtual void Excepter() override
    {
    }

    virtual ~Listener() override
    {
        _listen_sockfd_ptr->Close(); // 关闭listen套接字后析构  //析构函数名字相同，所以要设置成虚函数，否则会造成fd泄露
    }

    void Close()
    {
        if (_sockfd > 0)
            ::close(_sockfd);
    }

private:
    std::unique_ptr<Socket> _listen_sockfd_ptr;
    u_int16_t _port;

    Calculator cal;
    Parse parse;
};